package com.osexp.controller;

import com.osexp.model.Disk;
import com.osexp.model.Memory;
import com.osexp.model.TLB;
import com.osexp.model.Task;
import com.osexp.model.TaskQueue;
import com.osexp.model.oProcess;
import com.osexp.model.paraConstants;


public class PC implements paraConstants{
	Disk disk=null;
	Memory memory=null;
	TLB tlb=null;
	oProcess[] processes=null;
	TaskQueue taskQueue=null;
	Task currTask=null;
	int currTaskNum;
	Double currTime;
	int currReplacementAlgorithm;
	int currReplacementStrategy;

	public PC() {
		super();
		currTaskNum=0;
		currTime=0.0;
		currReplacementAlgorithm=1;
		currReplacementStrategy=0;
		this.disk = new Disk();
		this.memory = new Memory();
		this.tlb = new TLB();
		this.taskQueue=new TaskQueue();
		this.processes = new oProcess[5];
		for(int i=0;i<5;i++){
			processes[i]=new oProcess(i);
			memory.addPageTable(i);
			taskQueue.add(i, processes[i].gettList());
		}		
		taskQueue.sort();		
	}

	public String currPrint() {
		String temp=null;
//		System.out.println("TLB:");
//		System.out.println(tlb);
//		taskQueue.currPrint();
//		System.out.println("Current Time:");
		temp = "\nCurrent Time:\n";
//		System.out.println(currTime+"ns");
		temp +=currTime + "ns\n";
//		System.out.println("Execution Time:");
//		for(int i=0;i<5;i++){
//			System.out.println(processes[i].getExecutionTime()+"ns");			
//		}

//		System.out.println("Waiting Time:");
		temp += "Waiting Time:\n";
		for(int i=0;i<5;i++){
			temp += processes[i].getWaitTime().toString()+"\n";
//			System.out.println(processes[i].getWaitTime());
		}
		if (currTaskNum>=iTotalTask) {
			//任务完成
			return temp="\nPlease choose other choices to show!\n";
		}
		return temp;
	}	
	public String showTLB(){
		String temp = null;
		temp = "\nTLB:\n";
		temp += this.tlb.toString();
		return temp;
	}
	public String showMM(){
		String temp = null;
		temp = "\nMemory:\n";
		temp += this.memory.printPhysicalMemory();
		return temp;
	}
	
	public String Next() {
		String temp =null;
		if (currTaskNum>=iTotalTask) {
			//任务完成
			temp = null;
			return temp="\nFinish all Tasks!\n";
		}

		//获取当前任务
		currTask=taskQueue.next(currTaskNum);
		System.out.println("==========================Processing Task: "+(currTaskNum+1));
		temp = "\nProcessing Task: "+(currTaskNum+1);
		currTaskNum++;

		//计算等待时间
		// TODO: 让所有任务都能更新等待时间
		if(currTask.getdTime()<currTime){
			Double currWaitTime=processes[currTask.getPid()].getWaitTime();
			processes[currTask.getPid()].setWaitTime(currTime-currTask.getdTime()+currWaitTime);	
		}else{
			currTime=currTask.getdTime();
		}
	
		Double currExecTime=processes[currTask.getPid()].getExecutionTime();

		//主逻辑
		if(tlb.find(currTask.getiLogicalAddress())!=-1){			
			//在tlb中找到后计时
			System.out.println("Found in TLB");
			temp += "\nFound in TLB";
			Double timeUsed=iTLBTime+iMemoryTime+0.0;
			processes[currTask.getPid()].setExecutionTime(currExecTime+timeUsed);
			currTime+=timeUsed;
		}else{
			System.out.println("Not Found in TLB");
			temp += "\nNot Found in TLB";
			int memFound;
			if(currReplacementStrategy==0){
				if(currReplacementAlgorithm==0){
					memFound=memory.fifoFind(currTask.getPid(), currTask.getiLogicalAddress());	
				}else{
					memFound=memory.lruFind(currTask.getPid(), currTask.getiLogicalAddress());
				}								
			}else{
				if(currReplacementAlgorithm==0){
					memFound=memory.fifoFindPart(currTask.getPid(), currTask.getiLogicalAddress());
				}else{
					memFound=memory.lruFindPart(currTask.getPid(), currTask.getiLogicalAddress());
				}
				
			}
			
			if(memFound!=-1){
				System.out.println("Found in mem");
				temp += "\nFound in mem";
				if(currReplacementAlgorithm==0){
					tlb.fifoAdd(currTask.getiLogicalAddress(), memFound);
				}else{
					tlb.lruAdd(currTask.getiLogicalAddress(), memFound);
				}
				//TODO 待验证的计算				
				Double timeUsed=iTLBTime+iMemoryTime*2+0.0;
				processes[currTask.getPid()].setExecutionTime(currExecTime+timeUsed);
				currTime+=timeUsed;
			}else{
				System.out.println("Not Found in mem");	
				temp += "\nNot Found in mem";
				int memFoundAfterUpdate;
				if(currReplacementStrategy==0){
					if(currReplacementAlgorithm==0){
						memFoundAfterUpdate=memory.fifoFind(currTask.getPid(), currTask.getiLogicalAddress());
					}else{						
						memFoundAfterUpdate=memory.lruFind(currTask.getPid(), currTask.getiLogicalAddress());						
					}
					
				}else{
					if(currReplacementAlgorithm==0){
						memFoundAfterUpdate=memory.fifoFindPart(currTask.getPid(), currTask.getiLogicalAddress());
					}else{
						memFoundAfterUpdate=memory.lruFindPart(currTask.getPid(), currTask.getiLogicalAddress());
					}
					
				}
				tlb.fifoAdd(currTask.getiLogicalAddress(), memFoundAfterUpdate);
				if(currReplacementStrategy==0){
					for(int i3=0;i3<5;i3++){
						memory.memUpdate(i3, currTask.getiLogicalAddress(), memFoundAfterUpdate);
					}
				}				
				Double timeUsed=0.0;
				timeUsed+=disk.findTime(currTask.getiLogicalAddress());
				timeUsed+=iTLBTime*2+iMemoryTime*3;
				//TODO 待验证的计算				
				processes[currTask.getPid()].setExecutionTime(currExecTime+timeUsed);
				currTime+=timeUsed;
			}
		}
		return temp;
	}
	
	
	public int getCurrReplacementAlgorithm() {
		return currReplacementAlgorithm;
	}

	public void setCurrReplacementAlgorithm(int currReplacementAlgorithm) {
		this.currReplacementAlgorithm = currReplacementAlgorithm;
	}

	public int getCurrReplacementStrategy() {
		return currReplacementStrategy;
	}

	public void setCurrReplacementStrategy(int currReplacementStrategy) {
		this.currReplacementStrategy = currReplacementStrategy;
	}	
	
/*	public static void main(String[] args){
		PC pc=new PC();		
		pc.setCurrReplacementAlgorithm(1);//0=FIFO	1=LRU
		pc.setCurrReplacementStrategy(0);//0=全局 	1=局部
		for(int i=0;i<iTotalTask;i++){
			pc.Next();
			pc.currPrint();
		}		
	}
*/
	
}
